home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 10
/
AACD 10.iso
/
AACD
/
Games
/
MAME
/
src
/
vidhrdw
/
rpunch.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-04
|
12KB
|
502 lines
/***************************************************************************
vidhrdw/rpunch.c
Functions to emulate the video hardware of the machine.
****************************************************************************/
#ifndef INCLUDE_DRAW_CORE
#include "driver.h"
#include "vidhrdw/generic.h"
#define BITMAP_WIDTH 304
#define BITMAP_HEIGHT 224
#define BITMAP_XOFFSET 4
/*************************************
*
* Statics
*
*************************************/
UINT8 *rpunch_bitmapram;
size_t rpunch_bitmapram_size;
static UINT32 *rpunch_bitmapsum;
int rpunch_sprite_palette;
static struct tilemap *background[2];
static UINT16 videoflags;
static UINT8 crtc_register;
static void *crtc_timer;
static UINT8 bins, gins;
static const UINT16 *callback_videoram;
static UINT8 callback_gfxbank;
static UINT8 callback_colorbase;
static UINT16 callback_imagebase;
static UINT16 callback_imagemask;
/*************************************
*
* Prototypes
*
*************************************/
void rpunch_vh_stop(void);
static void draw_bitmap_8(struct osd_bitmap *bitmap);
static void draw_bitmap_16(struct osd_bitmap *bitmap);
/*************************************
*
* Tilemap callbacks
*
*************************************/
static void get_bg_tile_info(int tile_index)
{
int data = callback_videoram[tile_index];
SET_TILE_INFO(callback_gfxbank,
callback_imagebase | (data & callback_imagemask),
callback_colorbase | ((data >> 13) & 7));
}
/*************************************
*
* Video system start
*
*************************************/
static void crtc_interrupt_gen(int param)
{
cpu_cause_interrupt(0, 1);
if (param != 0)
crtc_timer = timer_pulse(TIME_IN_HZ(Machine->drv->frames_per_second * param), 0, crtc_interrupt_gen);
}
int rpunch_vh_start(void)
{
int i;
/* allocate tilemaps for the backgrounds and a bitmap for the direct-mapped bitmap */
background[0] = tilemap_create(get_bg_tile_info,tilemap_scan_cols,TILEMAP_OPAQUE, 8,8,64,64);
background[1] = tilemap_create(get_bg_tile_info,tilemap_scan_cols,TILEMAP_TRANSPARENT,8,8,64,64);
/* allocate a bitmap sum */
rpunch_bitmapsum = malloc(BITMAP_HEIGHT * sizeof(UINT32));
/* if anything failed, clean up and return an error */
if (!background[0] || !background[1] || !rpunch_bitmapsum)
{
rpunch_vh_stop();
return 1;
}
/* configure the tilemaps */
background[1]->transparent_pen = 15;
/* reset the sums and bitmap */
for (i = 0; i < BITMAP_HEIGHT; i++)
rpunch_bitmapsum[i] = (BITMAP_WIDTH/4) * 0xffff;
if (rpunch_bitmapram)
memset(rpunch_bitmapram, 0xff, rpunch_bitmapram_size);
/* reset the timer */
crtc_timer = NULL;
return 0;
}
/*************************************
*
* Video system shutdown
*
*************************************/
void rpunch_vh_stop(void)
{
if (rpunch_bitmapsum)
free(rpunch_bitmapsum);
rpunch_bitmapsum = NULL;
}
/*************************************
*
* Write handlers
*
*************************************/
WRITE_HANDLER(rpunch_bitmap_w)
{
if (rpunch_bitmapram)
{
int oldword = READ_WORD(&rpunch_bitmapram[offset]);
int newword = COMBINE_WORD(oldword, data);
if (oldword != newword)
{
int row = offset / 256;
int col = 2 * (offset % 256) - BITMAP_XOFFSET;
WRITE_WORD(&rpunch_bitmapram[offset], data);
if (row < BITMAP_HEIGHT && col >= 0 && col < BITMAP_WIDTH)
rpunch_bitmapsum[row] += newword - oldword;
}
}
}
WRITE_HANDLER(rpunch_videoram_w)
{
int oldword = READ_WORD(&videoram[offset]);
int newword = COMBINE_WORD(oldword, data);
if (oldword != newword)
{
int tilemap = offset >> 13;
int tile_index = (offset / 2) & 0xfff;
WRITE_WORD(&videoram[offset], newword);
tilemap_mark_tile_dirty(background[tilemap],tile_index);
}
}
WRITE_HANDLER(rpunch_videoreg_w)
{
int newword = COMBINE_WORD(videoflags, data);
if (videoflags != newword)
{
/* invalidate tilemaps */
if ((newword ^ videoflags) & 0x0410)
tilemap_mark_all_tiles_dirty(background[0]);
if ((newword ^ videoflags) & 0x0820)
tilemap_mark_all_tiles_dirty(background[1]);
videoflags = newword;
}
}
WRITE_HANDLER(rpunch_scrollreg_w)
{
switch (offset / 2)
{
case 0:
tilemap_set_scrolly(background[0], 0, data & 0x1ff);
break;
case 1:
tilemap_set_scrollx(background[0], 0, (data & 0x1ff) - 8);
break;
case 2:
tilemap_set_scrolly(background[1], 0, data & 0x1ff);
break;
case 3:
tilemap_set_scrollx(background[1], 0, data & 0x1ff);
break;
}
}
WRITE_HANDLER(rpunch_crtc_data_w)
{
if (!(data & 0x00ff0000))
{
data &= 0xff;
switch (crtc_register)
{
/* only register we know about.... */
case 0x0b:
if (crtc_timer)
timer_remove(crtc_timer);
crtc_timer = timer_set(cpu_getscanlinetime(Machine->drv->visible_area.max_y + 1), (data == 0xc0) ? 2 : 1, crtc_interrupt_gen);
break;
default:
logerror("CRTC register %02X = %02X\n", crtc_register, data & 0xff);
break;
}
}
}
WRITE_HANDLER(rpunch_crtc_register_w)
{
if (!(data & 0x00ff0000))
crtc_register = data & 0xff;
}
WRITE_HANDLER(rpunch_ins_w)
{
if (!(data & 0x00ff0000))
{
if (offset == 0)
{
gins = data & 0x3f;
logerror("GINS = %02X\n", data & 0x3f);
}
else
{
bins = data & 0x3f;
logerror("BINS = %02X\n", data & 0x3f);
}
}
}
/*************************************
*
* Sprite routines
*
*************************************/
static void mark_sprite_palette(void)
{
UINT16 used_colors[16];
int offs, i, j;
memset(used_colors, 0, sizeof(used_colors));
for (offs = 0; offs < spriteram_size; offs += 8)
{
int data1 = READ_WORD(&spriteram[offs + 2]);
int code = data1 & 0x7ff;
if (code < 0x600)
{
int data0 = READ_WORD(&spriteram[offs + 0]);
int data2 = READ_WORD(&spriteram[offs + 4]);
int x = (data2 & 0x1ff) + 8;
int y = 513 - (data0 & 0x1ff);
int color = ((data1 >> 13) & 7) | ((videoflags & 0x0040) >> 3);
if (x >= BITMAP_WIDTH) x -= 512;
if (y >= BITMAP_HEIGHT) y -= 512;
if (x > -16 && y > -32)
used_colors[color] |= Machine->gfx[2]->pen_usage[code];
}
}
for (i = 0; i < 16; i++)
{
UINT16 used = used_colors[i];
if (used)
{
for (j = 0; j < 15; j++)
if (used & (1 << j))
palette_used_colors[rpunch_sprite_palette + i * 16 + j] = PALETTE_COLOR_USED;
palette_used_colors[rpunch_sprite_palette + i * 16 + 15] = PALETTE_COLOR_TRANSPARENT;
}
}
}
static void draw_sprites(struct osd_bitmap *bitmap)
{
int offs;
/* draw the sprites */
for (offs = 0; offs < spriteram_size; offs += 8)
{
int data1 = READ_WORD(&spriteram[offs + 2]);
int code = data1 & 0x7ff;
if (code < 0x600)
{
int data0 = READ_WORD(&spriteram[offs + 0]);
int data2 = READ_WORD(&spriteram[offs + 4]);
int x = (data2 & 0x1ff) + 8;
int y = 513 - (data0 & 0x1ff);
int xflip = data1 & 0x1000;
int color = ((data1 >> 13) & 7) | ((videoflags & 0x0040) >> 3);
if (x >= BITMAP_WIDTH) x -= 512;
if (y >= BITMAP_HEIGHT) y -= 512;
drawgfx(bitmap, Machine->gfx[2],
code, color + (rpunch_sprite_palette / 16), xflip, 0, x, y, 0, TRANSPARENCY_PEN, 15);
}
}
}
/*************************************
*
* Main screen refresh
*
*************************************/
void rpunch_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
{
int x, penbase;
/* update background 0 */
callback_gfxbank = 0;
callback_videoram = (const UINT16 *)&videoram[0];
callback_colorbase = (videoflags & 0x0010) >> 1;
callback_imagebase = (videoflags & 0x0400) << 3;
callback_imagemask = callback_imagebase ? 0x0fff : 0x1fff;
tilemap_update(background[0]);
/* update background 1 */
callback_gfxbank = 1;
callback_videoram = (const UINT16 *)&videoram[videoram_size / 2];
callback_colorbase = (videoflags & 0x0020) >> 2;
callback_imagebase = (videoflags & 0x0800) << 2;
callback_imagemask = callback_imagebase ? 0x0fff : 0x1fff;
tilemap_update(background[1]);
/* update the palette usage */
palette_init_used_colors();
mark_sprite_palette();
if (rpunch_bitmapram)
{
penbase = 512 + (videoflags & 15);
for (x = 0; x < 15; x++)
palette_used_colors[penbase + x] = PALETTE_COLOR_USED;
palette_used_colors[penbase + 15] = PALETTE_COLOR_TRANSPARENT;
}
/* handle full refresh */
if (palette_recalc() || full_refresh)
tilemap_mark_all_pixels_dirty(ALL_TILEMAPS);
/* update the tilemaps */
tilemap_render(ALL_TILEMAPS);
/* build the result */
tilemap_draw(bitmap, background[0], 0);
/* if we have a bitmap layer, it goes on top */
if (rpunch_bitmapram)
{
tilemap_draw(bitmap, background[1], 0);
draw_sprites(bitmap);
if (bitmap->depth == 8)
draw_bitmap_8(bitmap);
else
draw_bitmap_16(bitmap);
}
/* otherwise, the second background layer gets top billing */
else
{
draw_sprites(bitmap);
tilemap_draw(bitmap, background[1], 0);
}
}
/*************************************
*
* Depth-specific refresh
*
*************************************/
#define ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, x, y, xadv) \
if (orientation) \
{ \
int dy = bitmap->line[1] - bitmap->line[0]; \
int tx = x, ty = y, temp; \
if (orientation & ORIENTATION_SWAP_XY) \
{ \
temp = tx; tx = ty; ty = temp; \
xadv = dy / (bitmap->depth / 8); \
} \
if (orientation & ORIENTATION_FLIP_X) \
{ \
tx = bitmap->width - 1 - tx; \
if (!(orientation & ORIENTATION_SWAP_XY)) xadv = -xadv; \
} \
if (orientation & ORIENTATION_FLIP_Y) \
{ \
ty = bitmap->height - 1 - ty; \
if ((orientation & ORIENTATION_SWAP_XY)) xadv = -xadv; \
} \
/* can't lookup line because it may be negative! */ \
dst = (TYPE *)(bitmap->line[0] + dy * ty) + tx; \
}
#define INCLUDE_DRAW_CORE
#define DRAW_FUNC draw_bitmap_8
#define TYPE UINT8
#include "rpunch.c"
#undef TYPE
#undef DRAW_FUNC
#define DRAW_FUNC draw_bitmap_16
#define TYPE UINT16
#include "rpunch.c"
#undef TYPE
#undef DRAW_FUNC
#else
/*************************************
*
* Core refresh routine
*
*************************************/
void DRAW_FUNC(struct osd_bitmap *bitmap)
{
UINT16 *pens = &Machine->pens[512 + (videoflags & 15) * 16];
int orientation = Machine->orientation;
int x, y;
/* draw any non-transparent scanlines from the VRAM directly */
for (y = 0; y < BITMAP_HEIGHT; y++)
if (rpunch_bitmapsum[y] != (BITMAP_WIDTH/4) * 0xffff)
{
UINT16 *src = (UINT16 *)&rpunch_bitmapram[y * 256 + BITMAP_XOFFSET/2];
TYPE *dst = (TYPE *)bitmap->line[y];
int xadv = 1;
/* adjust in case we're oddly oriented */
ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, 0, y, xadv);
/* redraw the scanline */
for (x = 0; x < BITMAP_WIDTH/4; x++)
{
int data = *src++;
if (data != 0xffff)
{
if ((data & 0xf000) != 0xf000)
*dst = pens[data >> 12];
dst += xadv;
if ((data & 0x0f00) != 0x0f00)
*dst = pens[(data >> 8) & 15];
dst += xadv;
if ((data & 0x00f0) != 0x00f0)
*dst = pens[(data >> 4) & 15];
dst += xadv;
if ((data & 0x000f) != 0x000f)
*dst = pens[data & 15];
dst += xadv;
}
else
dst += 4 * xadv;
}
}
}
#endif